package com.example.demo.core.util;

import com.example.demo.core.annotations.ApiNotNull;
import com.example.demo.core.exception.ProgramException;
import com.example.demo.model.TaskRunnable;
import com.example.demo.model.TaskSession;
import org.apache.commons.lang.StringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.CronTask;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 定时任务工具类
 *
 * @author yujie
 */
public class TaskUtil {

    private static final ConcurrentHashMap<TaskRunnable, TaskSession> CONCURRENT_TASK_HASH_MAP;

    private static final ThreadPoolTaskScheduler THREAD_POOL_TASK_SCHEDULER;

    static {
        CONCURRENT_TASK_HASH_MAP = new ConcurrentHashMap<>(16);
        THREAD_POOL_TASK_SCHEDULER = new ThreadPoolTaskScheduler();
        //线程池初始化定义
        THREAD_POOL_TASK_SCHEDULER.setPoolSize(20);
        THREAD_POOL_TASK_SCHEDULER.setThreadNamePrefix("taskExecutor-");
        THREAD_POOL_TASK_SCHEDULER.setWaitForTasksToCompleteOnShutdown(true);
        THREAD_POOL_TASK_SCHEDULER.setAwaitTerminationSeconds(60);
    }

    /**
     * 添加定时任务
     *
     * @param runnable 实现Runnable接口的自定义类
     * @param cron     时间表达式
     */
    public void addFuture(@ApiNotNull TaskRunnable runnable,@ApiNotNull String cron) {
        //先把以前的删掉，此操作也可不做
        removeFuture(runnable.getId());
        CronTask cronTask = new CronTask(runnable, cron);
        CONCURRENT_TASK_HASH_MAP.put(runnable, new TaskSession(THREAD_POOL_TASK_SCHEDULER.schedule(cronTask.getRunnable(), cronTask.getTrigger())));
    }

    /**
     * 删除定时任务类
     *
     * @param id 需要删除的定时类唯一标识
     */
    public void removeFuture(Integer id) {
        if (Objects.isNull(id)) {
            throw new ProgramException("参数错误");
        }
        for (Map.Entry<TaskRunnable, TaskSession> taskRunnableTaskSessionEntry : CONCURRENT_TASK_HASH_MAP.entrySet()) {
            TaskRunnable taskRunnable = taskRunnableTaskSessionEntry.getKey();
            if (taskRunnable.getId().equals(id)) {
                TaskSession oldTaskSession = CONCURRENT_TASK_HASH_MAP.remove(taskRunnable);
                if (!Objects.isNull(oldTaskSession)) {
                    oldTaskSession.cancel();
                }
            }
        }
    }

    /**
     * 判断该ID是否存在，存在则为true,不存在则为false
     *
     * @param id 唯一主键
     * @return boolean
     */
    public Boolean existsById(Integer id) {
        if (RegexUtil.checkObjectIsNull(id)) {
            throw new ProgramException("参数错误");
        }
        for (Map.Entry<TaskRunnable, TaskSession> taskRunnableTaskSessionEntry : CONCURRENT_TASK_HASH_MAP.entrySet()) {
            TaskRunnable taskRunnable = taskRunnableTaskSessionEntry.getKey();
            if (taskRunnable.getId().equals(id)) {
                TaskSession oldTaskSession = CONCURRENT_TASK_HASH_MAP.remove(taskRunnable);
                if (RegexUtil.checkObjectIsNotNull(oldTaskSession)) {
                    return true;
                }
            }
        }
        return false;
    }


}
